#ifndef __NET_EPOLL__
#define __NET_EPOLL__

#include<iostream>
#include<vector>
#include<unordered_map>

#include<string.h>
#include<errno.h>
#include<assert.h>
#include<sys/epoll.h>

#include"channel.hpp"

#define EPOLL_MAXNUM 1024
#define EPOLL_WAITTIME 20000


class Epoll
{
public:
    Epoll()
    {
        _epoll_fd=epoll_create1(EPOLL_CLOEXEC);
        assert(_epoll_fd>0);
    }

    //加入或修改监控事件
    void epoll_update(Channel* channel)
    {
        int op;
        if(!_epoll_channels.count(channel->get_fd()))
        {
            _epoll_channels[channel->get_fd()]=channel;
            op=EPOLL_CTL_ADD;
        }
        else op=EPOLL_CTL_MOD;
        update(channel,op);
    }

    //删除监控事件
    void epoll_remove(Channel* channel)
    {
        auto it=_epoll_channels.find(channel->get_fd());
        if(it!=_epoll_channels.end())_epoll_channels.erase(it->first);
        update(channel,EPOLL_CTL_DEL);
    }

    //开始监控连接
    int poll()
    {
        while(1)
        {
            //epoll开始监控连接，返回就绪连接数量，EPOLL_WAITTIME表示等待事件，-1表示阻塞等待
            // int event_count=epoll_wait(_epoll_fd,_epoll_events,EPOLL_MAXNUM,-1);
            int event_count=epoll_wait(_epoll_fd,_epoll_events,EPOLL_MAXNUM,EPOLL_WAITTIME);
            if(event_count<0)
            {
                ERR("epoll_wait failed, error no:%d, error str:&s",errno,strerror(errno));
                continue;
            }

            for(int i=0;i<event_count;i++)
            {
                auto it=_epoll_channels.find(_epoll_events[i].data.fd);
                assert(it!=_epoll_channels.end());
                it->second->set_revents(_epoll_events[i].events);
                it->second->handle_event();
            }
            return event_count;
        }
    }

private:
    //对epoll的时间表对应事件进行修改
    void update(Channel* channel,int op)
    {
        struct epoll_event ev;
        ev.events=channel->get_events();
        ev.data.fd=channel->get_fd();
        int ret=epoll_ctl(_epoll_fd,op,channel->get_fd(),&ev);
        if(ret<0) ERR("epoll_ctl failed!");
    }

private:
    int _epoll_fd;                                      //epoll的fd
    std::unordered_map<int,Channel*> _epoll_channels;   //epoll中存储的channel
    struct epoll_event _epoll_events[EPOLL_MAXNUM];     //epoll中存储的事件
};

#endif